home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / landma1a / map.cls < prev    next >
Encoding:
Visual Basic class definition  |  1999-10-10  |  25.8 KB  |  851 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4.   Persistable = 0  'NotPersistable
  5.   DataBindingBehavior = 0  'vbNone
  6.   DataSourceBehavior  = 0  'vbNone
  7.   MTSTransactionMode  = 0  'NotAnMTSObject
  8. END
  9. Attribute VB_Name = "Map"
  10. Attribute VB_GlobalNameSpace = False
  11. Attribute VB_Creatable = True
  12. Attribute VB_PredeclaredId = False
  13. Attribute VB_Exposed = False
  14. Option Explicit
  15. Option Base 1
  16.  
  17. Const XDIMENSION = 81
  18. Const YDIMENSION = 59
  19. Const UP = 1
  20. Const DOWN = 2
  21. Const LEFTY = 3
  22. Const RIGHTY = 4
  23. Const MAXIMUM_NEIGHBORS = 15
  24.  
  25. Dim Map(XDIMENSION, YDIMENSION) As Long
  26. 'Map Legend:
  27. '0   = Plain water during build process (empty square)
  28. 'x   = Country number x
  29. '999 = Coastline during build process
  30. '1000 and up = Bodies of water (determined after land placement)
  31.  
  32. Dim Tent(2, 150) As Long
  33. 'Tent(1,a) = x coordinate of point a
  34. 'Tent(2,a) = y coordinate of point a
  35.  
  36. Dim Seed(XDIMENSION, YDIMENSION) As Single
  37. 'The seed matrix contains the details of the random parts of the map.
  38. 'This is for display purposes only -- Just a tweak.
  39.  
  40. Dim Neighbor() As Long
  41. 'The Neighbor array will be populated with data about which
  42. 'countries border others:
  43. 'For example:  z = Neighbor(x,y)
  44. 'x  = Country in question
  45. 'y  = Index number
  46. 'z  = The country number of a neighboring country.  Unused indexes return 0.
  47. 'There will be no more than MAXIMUM_NEIGHBORS possible borders detected,
  48. 'but this should change if the resolution is increased.
  49.  
  50. Dim CountryClr() As Long
  51.  
  52. Dim Direction As Long
  53. Dim LastDirection As Long
  54. Dim TryNumber As Long
  55. Dim OneAway As Long
  56. Dim Country As Long
  57.  
  58. Dim Done As Boolean
  59. Dim CountryDone As Boolean
  60. Dim FoundLand As Boolean
  61. Dim FilledIn As Boolean
  62.  
  63. Dim i As Long
  64. Dim j As Long
  65. Dim k As Long
  66. Dim x As Long
  67. Dim y As Long
  68. Dim ii As Long
  69. Dim jj As Long
  70. Dim xx As Long
  71. Dim yy As Long
  72.  
  73. Public LakeCode As Long
  74. Public NumCountries As Integer
  75. Public MaxCountrySize As Integer
  76. Public MinLakeSize As Integer
  77.  
  78. Dim CountrySize As Integer
  79. Dim TentNum As Integer
  80. Dim Block As Integer
  81. Dim BlockTry As Integer
  82. Dim FudgeCounter As Integer
  83.  
  84. Public Property Get Xsize() As Integer
  85.     Xsize = XDIMENSION
  86. End Property
  87.  
  88. Public Property Get Ysize() As Integer
  89.     Ysize = YDIMENSION
  90. End Property
  91.  
  92. Public Property Get MaxNeighbors() As Integer
  93.     MaxNeighbors = MAXIMUM_NEIGHBORS
  94. End Property
  95.  
  96. Public Property Get Grid(x As Integer, y As Integer) As Long
  97.     Grid = Map(x, y)
  98. End Property
  99.  
  100. Public Property Get Neighbors(x As Integer, y As Integer) As Long
  101.     Neighbors = Neighbor(x, y)
  102. End Property
  103.  
  104. Public Property Get CountryColor(x As Integer) As Integer
  105.     CountryColor = CountryClr(x)
  106. End Property
  107.  
  108. Public Property Let CountryColor(x As Integer, y As Integer)
  109.     CountryClr(x) = y
  110. End Property
  111.  
  112.  
  113. Public Sub CreateMap(CountryCount As Integer, _
  114.                     MaximumCountrySize As Integer, _
  115.                     MinimumLakeSize As Integer, _
  116.                     LandPct As Double, _
  117.                     PropPct As Double, _
  118.                     ShapePct As Double, _
  119.                     CoastPctKeep As Double, _
  120.                     IslePctKeep As Double, _
  121.                     CFGColor As Integer, _
  122.                     CFGIslands As Integer)
  123.  
  124. 'We want some passed variables to stay public.
  125. NumCountries = CountryCount
  126. MaxCountrySize = MaximumCountrySize
  127. MinLakeSize = MinimumLakeSize
  128.  
  129. 'Redimension our arrays to save some memory.
  130. ReDim Neighbor(NumCountries, MAXIMUM_NEIGHBORS)
  131. ReDim CountryClr(NumCountries)
  132.  
  133. 'All of map is considered coastline for placing of first country.
  134. 'Also initializing seed matrix.
  135. For i = 1 To XDIMENSION
  136.   For j = 1 To YDIMENSION
  137.     Map(i, j) = 999
  138.     Seed(i, j) = Rnd(1)
  139.   Next j
  140. Next i
  141.  
  142. Country = 0
  143.  
  144. Do While Country < NumCountries
  145. Country = Country + 1
  146.  
  147. FudgeCounter = 0
  148.  
  149. 'Clear out the last country by clearing out the tentative array.
  150. For i = 1 To 2
  151.   For j = 1 To MaxCountrySize
  152.     Tent(i, j) = 0
  153.   Next j
  154. Next i
  155.  
  156. 'Main country loop.
  157. CountryDone = False
  158. Do Until CountryDone = True
  159.  
  160.   'Find the starting position of the next country.
  161.   Done = False
  162.   Do Until Done = True
  163.     x = Int(Rnd(1) * XDIMENSION) + 1
  164.     y = Int(Rnd(1) * YDIMENSION) + 1
  165.     'Take care of the None or Lots of Islands options.
  166.     If ((CFGIslands = 1) And (Map(x, y) = 999)) Then
  167.       Done = True
  168.     End If
  169.     If (CFGIslands = 3) And ((Map(x, y) = 0) Or (Map(x, y) = 999)) Then
  170.       Done = True
  171.     End If
  172.     'The 'Some Islands' option is more complex.
  173.     'If we found coastline, there's a large chance of keeping it.
  174.     'If we found empty, there's a small chance of keeping it.
  175.     If CFGIslands = 2 Then
  176.       If ((Map(x, y) = 999) And (Rnd(1) < CoastPctKeep)) Or ((Map(x, y) = 0) And (Rnd(1) < IslePctKeep)) Then
  177.         Done = True
  178.       End If
  179.     End If
  180.   Loop
  181.   Tent(1, 1) = x
  182.   Tent(2, 1) = y
  183.   
  184.   TentNum = 1
  185.   BlockTry = 0
  186.   
  187.   'Get a random size for this country.
  188.   CountrySize = MaxCountrySize - Int(Rnd(1) * (MaxCountrySize * PropPct))
  189.  
  190.   'Now we search for blocks contiguous to this one.
  191.   Do Until TentNum = CountrySize
  192.     'Regular or Irregular?
  193.     If Rnd(1) < ShapePct Then
  194.       Block = Int(Rnd(1) * TentNum) + 1
  195.     Else
  196.       Block = TentNum
  197.     End If
  198.     'Get the coordinates of a block in this country.
  199.     x = Tent(1, Block)
  200.     y = Tent(2, Block)
  201.     'Pick a random direction for a contiguous block.
  202.     Call NewDirection
  203.     Done = False
  204.     Do Until (TryNumber = 5 Or Done = True)
  205.       Select Case Direction
  206.         Case UP
  207.           OneAway = y - 1
  208.           If OneAway > 0 Then
  209.             'Check and see what's up.
  210.             If ClearDirection(x, OneAway) = True Then
  211.               'Map is clear in that direction.
  212.               y = y - 1
  213.               Call WriteToTent
  214.               Done = True
  215.             Else
  216.               'Blocked.  Try new direction.
  217.               Call NextDirection
  218.             End If
  219.           Else
  220.             'We went off the top.  Try new direction.
  221.             Call NextDirection
  222.           End If
  223.         Case DOWN
  224.           OneAway = y + 1
  225.           If OneAway <= YDIMENSION Then
  226.             'Check and see what's down.
  227.             If ClearDirection(x, OneAway) = True Then
  228.               'Map is clear in that direction.
  229.               y = y + 1
  230.               Call WriteToTent
  231.               Done = True
  232.             Else
  233.               'Blocked.  Try new direction.
  234.               Call NextDirection
  235.             End If
  236.           Else
  237.             'We went off the bottom.  Try new direction.
  238.             Call NextDirection
  239.           End If
  240.         Case LEFTY
  241.           OneAway = x - 1
  242.           If OneAway > 0 Then
  243.             'Check and see what's up.
  244.             If ClearDirection(OneAway, y) = True Then
  245.               'Map is clear in that direction.
  246.               x = x - 1
  247.               Call WriteToTent
  248.               Done = True
  249.             Else
  250.               'Blocked.  Try new direction.
  251.               Call NextDirection
  252.             End If
  253.           Else
  254.             'We went off the left.  Try new direction.
  255.             Call NextDirection
  256.           End If
  257.         Case RIGHTY
  258.           OneAway = x + 1
  259.           If OneAway <= XDIMENSION Then
  260.             'Check and see what's up.
  261.             If ClearDirection(OneAway, y) = True Then
  262.               'Map is clear in that direction.
  263.               x = x + 1
  264.               Call WriteToTent
  265.               Done = True
  266.             Else
  267.               'Blocked.  Try new direction.
  268.               Call NextDirection
  269.             End If
  270.           Else
  271.             'We went off the right.  Try new direction.
  272.             Call NextDirection
  273.           End If
  274.       End Select
  275.     Loop
  276.     If TryNumber = 5 Then
  277.       'This block is boxed in.  Try the next block in the country.
  278.       Block = Block + 1
  279.       If Block > TentNum Then
  280.         Block = 1
  281.       End If
  282.       'Have we tried all blocks?
  283.       BlockTry = BlockTry + 1
  284.       If BlockTry = TentNum Then
  285.         'This Country cannot fit.  Need new starting location.
  286.         TentNum = CountrySize   'Fudging out of loop.
  287.         FudgeCounter = FudgeCounter + 1
  288.         'Move on to next country if we can't place this one
  289.         'within a reasonable number of tries.
  290.         If (FudgeCounter > 2000) Then
  291.           CountryDone = True
  292.           Country = Country - 1
  293.           NumCountries = NumCountries - 1
  294.         End If
  295.       End If
  296.     End If
  297.   Loop
  298. Loop
  299.  
  300. 'Yay!  Our country is sitting in the Tent array.
  301. 'Let's copy it over to the Map.
  302. 'If we blew it last time, then we don't need to do anything here.
  303. If FudgeCounter <= 2000 Then
  304.   
  305. For i = 1 To CountrySize
  306.   Map(Tent(1, i), Tent(2, i)) = Country
  307. Next i
  308.  
  309. If CFGColor = 1 Then
  310.   CountryClr(Country) = Country Mod 10   'Earth Tones
  311. Else
  312.   CountryClr(Country) = 10   'White
  313. End If
  314.  
  315. 'Let's outline all countries on the map with coastline.
  316. 'Because if there are no islands, we must build on coastline next time.
  317. For i = 1 To XDIMENSION
  318.   For j = 1 To YDIMENSION
  319.     'If this was the first country, we erase all coastline.
  320.     If Country = 1 And Map(i, j) = 999 Then
  321.       Map(i, j) = 0
  322.     End If
  323.     'If coastline is already there, it stays there.
  324.     If Map(i, j) <> 999 Then
  325.       FoundLand = False
  326.       'Land up?
  327.       x = i
  328.       y = j - 1
  329.       If y > 0 Then
  330.         If Map(x, y) > 0 And Map(x, y) < 999 Then FoundLand = True
  331.       End If
  332.       'Land down?
  333.       x = i
  334.       y = j + 1
  335.       If y <= YDIMENSION Then
  336.         If Map(x, y) > 0 And Map(x, y) < 999 Then FoundLand = True
  337.       End If
  338.       'Land left?
  339.       x = i - 1
  340.       y = j
  341.       If x > 0 Then
  342.         If Map(x, y) > 0 And Map(x, y) < 999 Then FoundLand = True
  343.       End If
  344.       'Land right?
  345.       x = i + 1
  346.       y = j
  347.       If x <= XDIMENSION Then
  348.         If Map(x, y) > 0 And Map(x, y) < 999 Then FoundLand = True
  349.       End If
  350.       'Place coastline.
  351.       If FoundLand = True And Map(i, j) = 0 Then
  352.         Map(i, j) = 999
  353.       End If
  354.     End If
  355.   Next j
  356. Next i
  357.  
  358. End If
  359.  
  360. Loop    'Main country loop.
  361.  
  362. 'Fill in lakes according to lakesize parameter.
  363. Call FillLakes
  364.  
  365. 'Populate the Neighbors array.
  366. Call FindNeighbors
  367.  
  368. End Sub
  369.  
  370. Private Function WriteToTent()
  371.  
  372. 'Found a good contiguous block, lets record its X and Y.
  373. TentNum = TentNum + 1
  374. Tent(1, TentNum) = x
  375. Tent(2, TentNum) = y
  376.  
  377. 'Was this the last tentative block?  If so, we need to signal we're done.
  378. If TentNum = CountrySize Then
  379.   CountryDone = True
  380. End If
  381.  
  382. End Function
  383.  
  384. Private Function ClearDirection(Xcheck, Ycheck) As Boolean
  385.  
  386. 'This function checks the Map and Tent arrays to see if
  387. 'the suggested block is already used.
  388. ClearDirection = True
  389.  
  390. 'Is the suggested block part of another country?
  391. If Map(Xcheck, Ycheck) > 0 And Map(Xcheck, Ycheck) < 999 Then
  392.   ClearDirection = False
  393. End If
  394.  
  395. 'Is the suggested block part of the current country (or lake)?
  396. For i = 1 To TentNum
  397.   If Tent(1, i) = Xcheck And Tent(2, i) = Ycheck Then
  398.     ClearDirection = False
  399.   End If
  400. Next i
  401.  
  402. End Function
  403.  
  404. Private Function GetAdjacentColor(Xcheck, Ycheck)
  405.  
  406. If Map(Xcheck, Ycheck) <> 0 And Map(Xcheck, Ycheck) <> 999 And Country = 0 Then
  407.   Country = Map(Xcheck, Ycheck)
  408. End If
  409.  
  410. End Function
  411.  
  412. Private Function NextDirection()
  413.  
  414. 'The last direction didn't work, so we try the next until we've done them all.
  415. Direction = Direction + 1
  416. If Direction = 5 Then Direction = 1
  417. TryNumber = TryNumber + 1
  418.  
  419. End Function
  420.  
  421. Private Function NewDirection()
  422.  
  423. 'Record which way we went last time.
  424. LastDirection = Direction
  425. If LastDirection < 1 Or LastDirection > 4 Then
  426.   LastDirection = RandomDir
  427. End If
  428. Direction = RandomDir
  429. 'This will be our first try for a new way to go.
  430. TryNumber = 1
  431.  
  432. End Function
  433.  
  434. Public Function DisplayMap(Source As Long, Dest As Long, CFGBorders As Integer)
  435.  
  436. Dim PieceNum As Integer
  437. Dim LookUp As Integer
  438. Dim LookDown As Integer
  439. Dim LookLeft As Integer
  440. Dim LookRight As Integer
  441.  
  442. 'Lets update the map for everyone to see.
  443. For ii = 1 To XDIMENSION
  444.   For jj = 1 To YDIMENSION
  445.     If Map(ii, jj) > 0 And Map(ii, jj) < 999 Then
  446.       'This routine will determine which 'piece' gets used for this block.
  447.       'Initialize our counters.
  448.       PieceNum = 0
  449.       LookUp = -1
  450.       LookDown = -1
  451.       LookLeft = -1
  452.       LookRight = -1
  453.       'See if there's water or coastline to the right of us.
  454.       xx = ii + 1
  455.       yy = jj
  456.       If xx <= XDIMENSION Then
  457.         LookRight = Map(xx, yy)
  458.         If LookRight = 0 Or LookRight > 998 Then
  459.           PieceNum = PieceNum + 1   'Add a binary 1
  460.         End If
  461.       End If
  462.       'See if there's water or coastline to the left of us.
  463.       xx = ii - 1
  464.       yy = jj
  465.       If xx > 0 Then
  466.         LookLeft = Map(xx, yy)
  467.         If LookLeft = 0 Or LookLeft > 998 Then
  468.           PieceNum = PieceNum + 2   'Add a binary 2
  469.         End If
  470.       End If
  471.       'See if there's water or coastline below us.
  472.       xx = ii
  473.       yy = jj + 1
  474.       If yy <= YDIMENSION Then
  475.         LookDown = Map(xx, yy)
  476.         If LookDown = 0 Or LookDown > 998 Then
  477.           PieceNum = PieceNum + 4   'Add a binary 4
  478.         End If
  479.       End If
  480.       'See if there's water or coastline above us.
  481.       xx = ii
  482.       yy = jj - 1
  483.       If yy > 0 Then
  484.         LookUp = Map(xx, yy)
  485.         If LookUp = 0 Or LookUp > 998 Then
  486.           PieceNum = PieceNum + 8   'Add a binary 8
  487.         End If
  488.       End If
  489.       Call DrawBlock(Source, Dest, ii, jj, CountryClr(Map(ii, jj)), PieceNum + (19 * Int(Seed(ii, jj) * 4)))
  490.       
  491.       'Now we check for the edit pieces between countries to smooth out borders.
  492.       'Note that we *only* write on the current square.  We don't butt into
  493.       'someone else's country!
  494.       
  495.       'All this does is smooth out a corner of our square if a country is diagonal
  496.       'to us.
  497.       
  498.       'Check upper left.
  499.       If (LookUp = LookLeft) And (LookUp <> Map(ii, jj)) And (LookUp > 0) And (LookUp < 999) Then
  500.         Call DrawBlock(Source, Dest, ii, jj, CountryClr(LookUp), 15 + (19 * Int(Seed(ii, jj) * 4)))
  501.       End If
  502.       'Check upper right.
  503.       If (LookRight = LookUp) And (LookRight <> Map(ii, jj)) And (LookRight > 0) And (LookRight < 999) Then
  504.         Call DrawBlock(Source, Dest, ii, jj, CountryClr(LookRight), 16 + (19 * Int(Seed(ii, jj) * 4)))
  505.       End If
  506.       'Check lower left.
  507.       If (LookLeft = LookDown) And (LookLeft <> Map(ii, jj)) And (LookLeft > 0) And (LookLeft < 999) Then
  508.         Call DrawBlock(Source, Dest, ii, jj, CountryClr(LookLeft), 17 + (19 * Int(Seed(ii, jj) * 4)))
  509.       End If
  510.       'Check lower right.
  511.       If (LookDown = LookRight) And (LookDown <> Map(ii, jj)) And (LookDown > 0) And (LookDown < 999) Then
  512.         Call DrawBlock(Source, Dest, ii, jj, CountryClr(LookDown), 18 + (19 * Int(Seed(ii, jj) * 4)))
  513.       End If
  514.       
  515.       'We will also add the selected border if two adjacent squares are
  516.       'different countries.  If no border selected, then move on.
  517.       
  518.       If CFGBorders < 5 Then
  519.         'Check up.
  520.         If (LookUp <> Map(ii, jj)) And (LookUp > 0) And (LookUp < 999) Then
  521.           Call DrawBlock(Source, Dest, ii, jj, 12, 0 + (CFGBorders - 1) * 4)
  522.         End If
  523.         'Check right.
  524.         If (LookRight <> Map(ii, jj)) And (LookRight > 0) And (LookRight < 999) Then
  525.           Call DrawBlock(Source, Dest, ii, jj, 12, 2 + (CFGBorders - 1) * 4)
  526.         End If
  527.         'Check left.
  528.         If (LookLeft <> Map(ii, jj)) And (LookLeft > 0) And (LookLeft < 999) Then
  529.           Call DrawBlock(Source, Dest, ii, jj, 12, 3 + (CFGBorders - 1) * 4)
  530.         End If
  531.         'Check down.
  532.         If (LookDown <> Map(ii, jj)) And (LookDown > 0) And (LookDown < 999) Then
  533.           Call DrawBlock(Source, Dest, ii, jj, 12, 1 + (CFGBorders - 1) * 4)
  534.         End If
  535.       End If
  536.     End If
  537.   Next jj
  538. Next ii
  539.  
  540. End Function
  541.  
  542. Private Function DrawBlock(Source As Long, Dest As Long, x As Long, y As Long, Color As Long, PieceNum As Integer)
  543.  
  544. Dim PieceX As Integer
  545. Dim ColorY As Integer
  546.  
  547. PieceX = 8 * PieceNum
  548. ColorY = 16 * Color
  549.  
  550. BitBlt Dest, ((x - 1) * 8) + 10, (y - 1) * 8, 8, 8, Source, PieceX, ColorY + 8, SRCAND
  551. BitBlt Dest, ((x - 1) * 8) + 10, (y - 1) * 8, 8, 8, Source, PieceX, ColorY, SRCINVERT
  552.  
  553. End Function
  554.  
  555. Private Function RandomDir()
  556.  
  557. 'This function generates a random integer, 1-4.
  558. RandomDir = Int(Rnd(1) * 4) + 1
  559.  
  560. End Function
  561.  
  562. Private Function FillLakes()
  563.  
  564. 'This function checks for lakes on the entire map.
  565. 'If a lake is under the minimum size, then we fill it in
  566. 'with the color of a random adjacent country.
  567. 'If a lake is >= the minimum size, we will fill it in with
  568. 'the code for the next body of water (1000 and up).
  569. 'This will speed up the fill-in procedure so that each body
  570. 'of water is only tested once.  Also, we will be able to
  571. 'distinguish between lakes when we are done!
  572.  
  573. LakeCode = 1000
  574.  
  575. If MinLakeSize = 0 Then
  576.   'If we chose No Lake Correction, we need to plant seeds so that we
  577.   'can still identify bodies of water.
  578.   For j = 1 To XDIMENSION
  579.     For k = 1 To YDIMENSION
  580.       If Map(j, k) = 999 Then
  581.         Map(j, k) = LakeCode
  582.         Call LabelBodyOfWater(LakeCode)
  583.         LakeCode = LakeCode + 1
  584.       End If
  585.     Next k
  586.   Next j
  587.   Exit Function
  588. End If
  589.  
  590. For j = 1 To XDIMENSION
  591.   For k = 1 To YDIMENSION
  592.     'We always start our lake search on coastline.
  593.     FilledIn = False
  594.     If Map(j, k) = 999 Then
  595.       
  596.       'Clear out the last lake by clearing out the tentative array.
  597.       For i = 1 To MinLakeSize
  598.         Tent(1, i) = 0
  599.         Tent(2, i) = 0
  600.       Next i
  601.       
  602.       Tent(1, 1) = j
  603.       Tent(2, 1) = k
  604.       TentNum = 1
  605.       Country = 0
  606.       Block = 1
  607.  
  608.       'Now we search for blocks contiguous to this one.
  609.       Do Until TentNum = MinLakeSize
  610.         'Get the coordinates of a block in this country.
  611.         x = Tent(1, Block)
  612.         y = Tent(2, Block)
  613.         'Pick a direction to look for a contiguous block.
  614.         Direction = 1
  615.         Done = False
  616.         Do Until (Direction = 5 Or Done = True)
  617.         Select Case Direction
  618.           Case UP
  619.             OneAway = y - 1
  620.             If OneAway > 0 Then
  621.               'Check and see what's up.
  622.               If ClearDirection(x, OneAway) = True Then
  623.                 'Map is clear in that direction.
  624.                 y = y - 1
  625.                 Call WriteToTent
  626.                 Done = True
  627.               Else
  628.                 'Blocked.  Try new direction.
  629.                 Call GetAdjacentColor(x, OneAway)
  630.                 Direction = Direction + 1
  631.               End If
  632.             Else
  633.               'We went off the top.  Try new direction.
  634.               Direction = Direction + 1
  635.             End If
  636.           Case DOWN
  637.             OneAway = y + 1
  638.             If OneAway <= YDIMENSION Then
  639.               'Check and see what's down.
  640.               If ClearDirection(x, OneAway) = True Then
  641.                 'Map is clear in that direction.
  642.                 y = y + 1
  643.                 Call WriteToTent
  644.                 Done = True
  645.               Else
  646.                 'Blocked.  Try new direction.
  647.                 Call GetAdjacentColor(x, OneAway)
  648.                 Direction = Direction + 1
  649.               End If
  650.             Else
  651.               'We went off the bottom.  Try new direction.
  652.               Direction = Direction + 1
  653.             End If
  654.           Case LEFTY
  655.             OneAway = x - 1
  656.             If OneAway > 0 Then
  657.               'Check and see what's up.
  658.               If ClearDirection(OneAway, y) = True Then
  659.                 'Map is clear in that direction.
  660.                 x = x - 1
  661.                 Call WriteToTent
  662.                 Done = True
  663.               Else
  664.                 'Blocked.  Try new direction.
  665.                 Call GetAdjacentColor(OneAway, y)
  666.                 Direction = Direction + 1
  667.               End If
  668.             Else
  669.               'We went off the left.  Try new direction.
  670.               Direction = Direction + 1
  671.             End If
  672.           Case RIGHTY
  673.             OneAway = x + 1
  674.             If OneAway <= XDIMENSION Then
  675.               'Check and see what's up.
  676.               If ClearDirection(OneAway, y) = True Then
  677.                 'Map is clear in that direction.
  678.                 x = x + 1
  679.                 Call WriteToTent
  680.                 Done = True
  681.               Else
  682.                 'Blocked.  Try new direction.
  683.                 Call GetAdjacentColor(OneAway, y)
  684.                 Direction = Direction + 1
  685.               End If
  686.             Else
  687.               'We went off the right.  Try new direction.
  688.               Direction = Direction + 1
  689.             End If
  690.         End Select
  691.         Loop
  692.         If Direction = 5 Then
  693.           'This block is boxed in.  Try the next block in the lake.
  694.           Block = Block + 1
  695.           If Block > TentNum Then
  696.             'Minimum lake can't fit here -- need to fill it in.
  697.             For i = 1 To TentNum
  698.               Map(Tent(1, i), Tent(2, i)) = Country
  699.             Next i
  700.             TentNum = MinLakeSize   'Fudging out of loop.
  701.             FilledIn = True
  702.           End If
  703.         End If
  704.         If Done = True Then
  705.           Block = 1
  706.         End If
  707.       Loop
  708.       If FilledIn = False Then
  709.         'We've reached the minimum lake size.  Now we need to identify this
  710.         'entire body of water with the next lake code.  'Note that we overwrite
  711.         'our coastline here -- we don't need it anymore.
  712.         
  713.         'Part one of this procedure is to fill in the lake part we've
  714.         'found already.
  715.         For i = 1 To TentNum
  716.           Map(Tent(1, i), Tent(2, i)) = LakeCode
  717.         Next i
  718.         
  719.         'Part two of this procedure is to keep filling in the lake until
  720.         'there is no more to fill in.  We do this with quick multiple passes.
  721.         Call LabelBodyOfWater(LakeCode)
  722.         LakeCode = LakeCode + 1
  723.         
  724.       End If
  725.     End If
  726.   Next k
  727. Next j
  728. End Function
  729. Private Sub LabelBodyOfWater(LakeCode As Long)
  730.  
  731.         Done = False
  732.         Do While Done = False
  733.           Done = True  'If nothing gets written this pass, this will stay.
  734.           For ii = 1 To XDIMENSION
  735.             For jj = 1 To YDIMENSION
  736.               If Map(ii, jj) = LakeCode Then
  737.                 'Check for all adjacent squares and fill them in if they are
  738.                 'water or coastline.  Note that we do diagonals here!
  739.                 xx = ii
  740.                 yy = jj
  741.                 'Check up.
  742.                 If yy - 1 > 0 Then
  743.                   If Map(xx, yy - 1) = 0 Or Map(xx, yy - 1) = 999 Then
  744.                     Map(xx, yy - 1) = LakeCode
  745.                     Done = False
  746.                   End If
  747.                   'Check upper left.
  748.                   If xx - 1 > 0 Then
  749.                     If Map(xx - 1, yy - 1) = 0 Or Map(xx - 1, yy - 1) = 999 Then
  750.                       Map(xx - 1, yy - 1) = LakeCode
  751.                       Done = False
  752.                     End If
  753.                   End If
  754.                 End If
  755.                 'Check down.
  756.                 If yy + 1 <= YDIMENSION Then
  757.                   If Map(xx, yy + 1) = 0 Or Map(xx, yy + 1) = 999 Then
  758.                     Map(xx, yy + 1) = LakeCode
  759.                     Done = False
  760.                   End If
  761.                   'Check lower right.
  762.                   If xx + 1 <= XDIMENSION Then
  763.                     If Map(xx + 1, yy + 1) = 0 Or Map(xx + 1, yy + 1) = 999 Then
  764.                       Map(xx + 1, yy + 1) = LakeCode
  765.                       Done = False
  766.                     End If
  767.                   End If
  768.                 End If
  769.                 'Check left.
  770.                 If xx - 1 > 0 Then
  771.                   If Map(xx - 1, yy) = 0 Or Map(xx - 1, yy) = 999 Then
  772.                     Map(xx - 1, yy) = LakeCode
  773.                     Done = False
  774.                   End If
  775.                   'Check lower left.
  776.                   If yy + 1 <= YDIMENSION Then
  777.                     If Map(xx - 1, yy + 1) = 0 Or Map(xx - 1, yy + 1) = 999 Then
  778.                       Map(xx - 1, yy + 1) = LakeCode
  779.                       Done = False
  780.                     End If
  781.                   End If
  782.                 End If
  783.                 'Check right.
  784.                 If xx + 1 <= XDIMENSION Then
  785.                   If Map(xx + 1, yy) = 0 Or Map(xx + 1, yy) = 999 Then
  786.                     Map(xx + 1, yy) = LakeCode
  787.                     Done = False
  788.                   End If
  789.                   'Check upper right.
  790.                   If yy - 1 > 0 Then
  791.                     If Map(xx + 1, yy - 1) = 0 Or Map(xx + 1, yy - 1) = 999 Then
  792.                       Map(xx + 1, yy - 1) = LakeCode
  793.                       Done = False
  794.                     End If
  795.                   End If
  796.                 End If
  797.               End If
  798.             Next jj
  799.           Next ii
  800.         Loop
  801.  
  802. End Sub
  803.  
  804. Private Sub FindNeighbors()
  805.  
  806. 'This routine will populate the Neighbors array.
  807. For i = 1 To NumCountries
  808.   For j = 1 To MAXIMUM_NEIGHBORS
  809.     Neighbor(i, j) = 0
  810.   Next j
  811. Next i
  812.  
  813. For i = 1 To XDIMENSION
  814.   For j = 1 To YDIMENSION
  815.     x = i
  816.     y = j
  817.     'See what's up.
  818.     If y - 1 > 0 Then Call AddNeighbor(Map(x, y), Map(x, y - 1))
  819.     'See what's down.
  820.     If y + 1 <= YDIMENSION Then Call AddNeighbor(Map(x, y), Map(x, y + 1))
  821.     'See what's left.
  822.     If x - 1 > 0 Then Call AddNeighbor(Map(x, y), Map(x - 1, y))
  823.     'See what's right.
  824.     If x + 1 <= XDIMENSION Then Call AddNeighbor(Map(x, y), Map(x + 1, y))
  825.   Next j
  826. Next i
  827.  
  828. End Sub
  829.  
  830. Private Sub AddNeighbor(ToCountry As Long, NewNeighbor As Long)
  831.  
  832. 'This sub works with FindNeighbors to populate the Neighbors array.
  833.  
  834. If ToCountry > 998 Then Exit Sub  'This is water!
  835. If ToCountry = NewNeighbor Then Exit Sub  'Can't be our own neighbor!
  836.  
  837. Dim LastOne As Integer
  838.  
  839. LastOne = -1
  840.  
  841. For k = 1 To MAXIMUM_NEIGHBORS
  842.   If Neighbor(ToCountry, k) = NewNeighbor Then Exit Sub  'Already there.
  843.   If LastOne = -1 And Neighbor(ToCountry, k) = 0 Then LastOne = k
  844. Next k
  845.  
  846. If LastOne = -1 Then MsgBox ("There were too many bordering countries found."): Exit Sub
  847.  
  848. Neighbor(ToCountry, LastOne) = NewNeighbor
  849.  
  850. End Sub
  851.